from datetime import datetime, timedelta, date, time
from decimal import Decimal
from typing import List, Optional

from sqlalchemy import desc, func, and_, or_
from sqlalchemy.orm import Session, joinedload

from backend.db.database import SessionLocal
from backend.models.member import Member
from backend.models.member_transaction import Transaction, TransactionType
from backend.schemas.member_pydantic import TransactionResponse


class ConsumptionService:
    """消费记录服务类"""

    def __init__(self, session: Session):
        self.session = session

    def add_consumption(self, member_id: int, amount: Decimal, description: str = '消费') -> Transaction:
        """
        添加消费记录，
        返回消费orm对象
        """
        # 获取会员信息
        member = self.session.query(Member).filter(Member.id == member_id).first()
        if not member:
            raise ValueError(f"会员不存在 (ID: {member_id})")
            # 检查余额是否充足
        if member.current_balance < amount:
            raise ValueError(f"余额不足，当前余额: ¥{member.current_balance}, 消费金额: ¥{amount}")
        transaction = Transaction(member_id=member_id,
                                  transaction_type=TransactionType.CONSUMPTION,
                                  amount=amount,
                                  description=description)
        # 更新会员余额和统计信息
        member.current_balance -= Decimal(str(amount))
        member.total_consumption += Decimal(str(amount))
        member.consumption_count += 1
        member.last_consumption_date = datetime.now()
        self.session.add(transaction)
        self.session.commit()
        self.session.refresh(transaction)
        return transaction

    def add_recharge(self, member_id: int, amount: Decimal, description: str = "充值") -> Transaction:
        """添加充值记录"""
        # 获取会员信息
        member = self.session.query(Member).filter(Member.id == member_id).first()
        if not member:
            raise ValueError(f"会员不存在 (ID: {member_id})")

        # 创建充值记录
        transaction = Transaction(
            member_id=member_id,
            transaction_type=TransactionType.RECHARGE,
            amount=amount,
            description=description
        )

        # 更新会员余额
        print(type(member.current_balance))
        member.current_balance += Decimal(str(amount))

        self.session.add(transaction)
        self.session.commit()
        self.session.refresh(transaction)

        return transaction

    def add_refund(self, transaction_id: int, member_id: int, amount: Decimal,
                   description: str = "退款") -> Transaction:
        """添加退款记录"""
        # 获取会员信息
        member = self.session.query(Member).filter(Member.id == member_id).first()
        if not member:
            raise ValueError(f"会员不存在 (ID: {member_id})")
        # 获取交易记录
        check_transaction = self.session.query(Transaction).filter(Transaction.id == transaction_id).first()
        if not check_transaction:
            raise ValueError(f"没有这款交易 (ID: {transaction_id})")
        check_transaction.transaction_state = '已退款'

        # 创建退款记录
        transaction = Transaction(
            member_id=member_id,
            transaction_type=TransactionType.REFUND,
            amount=amount,
            description=description
        )

        # 更新会员余额（退款增加余额，但不影响总消费）
        member.current_balance += Decimal(str(amount))

        self.session.add(transaction)
        self.session.commit()
        self.session.refresh(transaction)

        return transaction

    def get_member_transactions(self, member_id: int, skip: int = 0, limit: int = 100) -> List[Transaction]:
        """获取会员的交易记录"""
        return self.session.query(Transaction).filter(
            Transaction.member_id == member_id
        ).order_by(desc(Transaction.transaction_date)).offset(skip).limit(limit).all()

    def get_transaction_by_id(self, transaction_id: int) -> Optional[Transaction]:
        """根据交易ID获取交易记录"""
        return self.session.query(Transaction).filter(Transaction.id == transaction_id).first()

    def get_recent_transactions(self, days: int = 7, limit: int = 50) -> List[Transaction]:
        """获取最近7天的交易记录,最多50条"""
        start_date = datetime.now() - timedelta(days=days)
        a = Transaction.zh_cn_display
        rows = self.session.query(Transaction).options(joinedload(
            Transaction.member
        )).filter(
            Transaction.transaction_date >= start_date
        ).order_by(
            desc(Transaction.transaction_date)
        ).limit(limit).all()
        response_list = []
        for row in rows:
            response = TransactionResponse(
                id=row.id,
                member_id=row.member_id,
                member_name=row.member.name,
                amount=row.amount,
                description=row.description,
                transaction_date=row.transaction_date,
                amount_display=row.amount_display,
                zh_cn_display=row.zh_cn_display,
                transaction_state=row.transaction_state
            )
            response_list.append(response)
        return response_list

    def get_daily_consumption_stats(self, start_date: date, end_date: date) -> List[dict]:
        """获取指定日期范围的每日消费统计"""
        results = self.session.query(
            func.date(Transaction.transaction_date).label('date'),
            func.sum(Transaction.amount).label('total_amount'),
            func.count(Transaction.id).label('transaction_count')
        ).filter(
            and_(
                Transaction.transaction_type == TransactionType.CONSUMPTION,
                func.date(Transaction.transaction_date).between(start_date, end_date)
            )
        ).group_by(func.date(Transaction.transaction_date)).all()

        return [
            {
                'date': result.date,  # 日期

                'total_amount': float(result.total_amount),  # 当日总消费额

                'transaction_count': result.transaction_count,  # 消费次数

            }
            for result in results
        ]

    def get_member_consumption_summary(self, member_id: int) -> dict:
        """获取会员消费汇总信息"""
        member = self.session.query(Member).filter(Member.id == member_id).first()
        if not member:
            raise ValueError(f"会员不存在 (ID: {member_id})")

        # 获取最近消费记录
        recent_transactions = self.get_member_transactions(member_id, limit=10)
        """最近消费记录"""
        # 计算本月消费
        now = datetime.now()
        month_start = datetime(now.year, now.month, 1)
        month_consumption = self.session.query(func.sum(Transaction.amount)).filter(
            and_(
                Transaction.member_id == member_id,
                Transaction.transaction_type == TransactionType.CONSUMPTION,
                Transaction.transaction_date >= month_start
            )
        ).scalar() or Decimal("0.00")
        """计算本月消费"""
        # 计算平均单次消费
        avg_consumption = Decimal("0.00")
        """平均消费"""
        if member.consumption_count > 0:
            avg_consumption = member.total_consumption / member.consumption_count

        return {
            'member': member,
            'recent_transactions': recent_transactions,
            'month_consumption': float(month_consumption),
            'avg_consumption': float(avg_consumption),
            'balance_status': member.balance_status
        }

    def update_member_balance(self, member_id: int) -> Member:
        """重新计算会员余额（用于数据修复）"""
        member = self.session.query(Member).filter(Member.id == member_id).first()
        if not member:
            raise ValueError(f"会员不存在 (ID: {member_id})")

        # 计算所有充值金额
        total_recharge = self.session.query(func.sum(Transaction.amount)).filter(
            and_(
                Transaction.member_id == member_id,
                Transaction.transaction_type.in_([TransactionType.RECHARGE, TransactionType.REFUND])
            )
        ).scalar() or Decimal("0.00")

        # 计算所有消费金额
        total_consumption = self.session.query(func.sum(Transaction.amount)).filter(
            and_(
                Transaction.member_id == member_id,
                Transaction.transaction_type == TransactionType.CONSUMPTION
            )
        ).scalar() or Decimal("0.00")

        # 计算消费次数
        consumption_count = self.session.query(func.count(Transaction.id)).filter(
            and_(
                Transaction.member_id == member_id,
                Transaction.transaction_type == TransactionType.CONSUMPTION
            )
        ).scalar() or 0

        # 获取最后消费时间
        last_consumption = self.session.query(Transaction).filter(
            and_(
                Transaction.member_id == member_id,
                Transaction.transaction_type == TransactionType.CONSUMPTION
            )
        ).order_by(desc(Transaction.transaction_date)).first()

        # 更新会员信息
        member.current_balance = total_recharge - total_consumption
        member.total_consumption = total_consumption
        member.consumption_count = consumption_count
        member.last_consumption_date = last_consumption.transaction_date if last_consumption else None
        member.updated_at = datetime.now()

        self.session.commit()
        self.session.refresh(member)

        return member

    def delete_transaction(self, transaction_id: int) -> bool:
        """删除交易记录并更新会员余额"""
        transaction = self.get_transaction_by_id(transaction_id)
        if not transaction:
            return False

        member_id = transaction.member_id

        # 删除交易记录
        self.session.delete(transaction)
        self.session.commit()

        # 重新计算会员余额
        self.update_member_balance(member_id)

        return True

    def all_get_consumptions(self, keyword=None):
        """获取会员交易记录"""
        if keyword is None:
            results = self.session.query(Transaction).all()
            return return_list(results)
        query = self.session.query(Transaction).join(Member)
        filters = []
        if str(keyword).isdigit():
            filters.append(Transaction.id == int(keyword))
            filters.append(Transaction.member_id == int(keyword))
        filters.append(Member.name.like(f"%{keyword}%"))
        results = query.filter(or_(*filters)).options(joinedload(Transaction.member)).all()
        return return_list(results)

    def get_designate_consumption(self, start_date: date = None, end_date: date = None, keyword=None):
        """通过时间，日期，姓名来筛选"""
        query = self.session.query(Transaction).join(Member)
        name_filters = []
        if keyword is not None:
            kw = str(keyword).strip()
            if kw:
                if kw.isdigit():
                    name_filters.append(Transaction.id == int(kw))
                    name_filters.append(Transaction.member_id == int(kw))
                name_filters.append(Member.name.like(f"%{kw}%"))
        time_filters = []
        if start_date:
            time_filters.append(Transaction.transaction_date >= datetime.combine(start_date, time.min))
        if end_date:
            time_filters.append(Transaction.transaction_date <= datetime.combine(end_date, time.max))
        filters = []
        if name_filters:
            filters.append(or_(*name_filters))
        if time_filters:
            filters.append(and_(*time_filters))
        results = query.filter(*filters).options(joinedload(Transaction.member)).all()
        return return_list(results)


def return_list(data):
    """设置返回参数"""
    list_transaction = []
    for result in data:
        result_1 = TransactionResponse(
            member_name=result.member.name,
            member_id=result.member.id,
            id=result.id,
            amount=result.amount,
            transaction_date=result.transaction_date,
            zh_cn_display=result.zh_cn_display,
            amount_display=result.amount_display,
            transaction_state=result.transaction_state,
            description=result.description)
        list_transaction.append(result_1)
    return list_transaction


if __name__ == '__main__':
    with SessionLocal() as se:
        consumption_service = ConsumptionService(se)
        start = date(2025, 10, 9)
        end = date(2025, 10, 31)
        a = consumption_service.get_designate_consumption()
        print(a)
